package vn.lumi.smarthome.service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import vn.lumi.smarthome.LumiHome;
import vn.lumi.smarthome.R;
import vn.lumi.smarthome.network.*;
import vn.lumi.smarthome.ui.LoginActivity;
import vn.lumi.smarthome.ui.MainActivity;

import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.util.Log;
import android.widget.Toast;

public class SmartHomeService extends Service {

	// msg code for intents from UI
	public static final int UI2SER_NEW_MSG = 0;
	public static final int UI2SER_RECONNECT_HC = 1;
	public static final int UI2SER_END_APPLICATION = 2;
	public static final int SER2UI_MSG_SUCCESSFUL = 3;
	public static final int SER2UI_MSG_FAILED = 4;
	public static final int SER2UI_NEW_DEVICE_STATUS = 5;
	public static final int SER2UI_ALL_DEVICE_STATUS = 6;
	public static final int SER2UI_NEW_CONFIG = 7;

	// msg code from threads
	public static final int SER2TRAN_NEW_MSG = 20;
	public static final int SER2TRAN_END_THREAD = 21;
	public static final int SER2TRAN_RESET = 22;

	public static final int SER2RECEI_END_THREAD = 30;
	public static final int SER2RECEI_RESET = 31;
	public static final int RECEI2SER_NEW_MSG = 32;

	public static final int RECON2SER_SUCESSFUL = 40;
	public static final int RECON2SER_FAILED_NONETWORK = 41;
	public static final int RECON2SER_FAILED_CANNOT_CONNECT = 42;
	public static final int RECON2SER_FAILED_SESSION_DELETED = 43;

	// register as clients
	public static final int MSG_REGISTER_CLIENT = 50;
	public static final int MSG_UNREGISTER_CLIENT = 51;

	// display toast
	public static final int MSG_DISPLAY_TOAST = 60;
	public static final String ToastTextKey = "Text for Toast";

	public static final String MESSAGE = "Msg";
	public static final String TIMEOUT = "Timeout";
	public static final String RETRY = "Retry";

	private ArrayList<Message2HC> Msg2HC = new ArrayList<Message2HC>();
	private final Messenger mMessenger = new Messenger(
			new IncomingMessageHandler()); // Target we publish for clients to
											// send messages to IncomingHandler.
	private List<Messenger> mClients = new ArrayList<Messenger>(); // Keeps
																	// track of
																	// all
																	// current
																	// registered
																	// clients.

	private Handler toastHandler = null;
	ReceiveDataThread receiveThread = null;
	TransmitThread transmitThread = null;

	static LumiHome myApp;
	// socket

	public Handler mHandler;

	public static boolean isRunning = false;

	private int current_Msg_id = 1;
	private Timer keepAliveTimer = null;

	@Override
	public IBinder onBind(Intent intent) {
		return mMessenger.getBinder();
	}

	public static boolean isRunning() {
		return isRunning;
	}

	@SuppressLint("HandlerLeak")
	@Override
	public void onCreate() {
		isRunning = true;
		myApp = (LumiHome) getApplication();
		mHandler = new IncomingMessageHandler();
		Log.d("Service", " created");
		receiveThread = new ReceiveDataThread(LumiHome.is, mHandler);
		receiveThread.start();
		transmitThread = new TransmitThread(myApp, mHandler);
		transmitThread.start();

		// display toast
		toastHandler = new Handler() {
			public void handleMessage(Message msg) {
				if (msg.what == MSG_DISPLAY_TOAST) {

					Bundle b = msg.getData();
					int textID = b.getInt(ToastTextKey);
					DisplayToast(textID, 1500);
				}
			}
		};

		// keepalive
		keepAliveTimer = new Timer();
		keepAliveTimer.scheduleAtFixedRate(new TimerTask() {
			@Override
			public void run() {
				if (isRunning == false)
					this.cancel();
				else {
					if (LumiHome.SocketState != LumiHome.SOCKET_RECONNECTING) {
						KeepAlive keepAlive = new KeepAlive(0, LumiHome.Uid,
								LumiHome.Session_id);
						// Create a new Msg2HC
						Message2HC Msg = new Message2HC(
								getApplicationContext(), current_Msg_id,
								keepAlive, LumiHome.Timeout);
						current_Msg_id++;
						if (current_Msg_id > 250)
							current_Msg_id = 1;
						Msg2HC.add(Msg);
						Log.d("Service", "KeepAlive created");
						Log.d("Service", "Msg2HC buffer=" + Msg2HC.size());
						Msg.startTimer();
					}
				}
			}
		}, 30000, 120000);
	}

	@Override
	public void onDestroy() {
		Log.d("Service", "stop now, bye bye!!!");
		if (keepAliveTimer != null) {
			keepAliveTimer.cancel();
		}
		isRunning = false;
		try {
			LumiHome.os.close();
			LumiHome.is.close();
			LumiHome.socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		super.onDestroy();

	}

	@Override
	public void onStart(Intent intent, int startid) {
		// Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
	}

	@SuppressLint("HandlerLeak")
	class IncomingMessageHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case 1000:
				Log.d("Service", "CP :End app");
				break;
			case UI2SER_END_APPLICATION:
				// Log.d("Service", "CP: end application");
				// receiveThread.End();
				// transmitThread.End();
				// isRunning = false;
				// stopService();
				break;
			case UI2SER_NEW_MSG:
				// Take out the message
				Bundle b = new Bundle();
				b = msg.getData();
				int MsgType = b.getInt("Message Type");
				if (MsgType == NetMessage.CMD_APP_CONTROL_NORMAL) {
					ControlNormalDevice appMsg = b
							.getParcelable("ContentProvider Message");
					Log.d("Service", "CP: New Msg, type = ControlNormalDevice");
					// Create a new Msg2HC
					Message2HC Msg = new Message2HC(getApplicationContext(),
							current_Msg_id, appMsg, LumiHome.Timeout);
					current_Msg_id++;
					if (current_Msg_id > 250)
						current_Msg_id = 1;
					Msg2HC.add(Msg);
					Log.d("Service", "Msg2HC buffer=" + Msg2HC.size());
					Msg.startTimer();
				} else if (MsgType == NetMessage.CMD_APP_CONTROL_RGB) {
					ControlRGB appMsg = b
							.getParcelable("ContentProvider Message");
					Log.d("Service", "CP: New Msg, type = ControlRGB");
					// Create a new Msg2HC
					Message2HC Msg = new Message2HC(getApplicationContext(),
							current_Msg_id, appMsg, LumiHome.Timeout);
					current_Msg_id++;
					if (current_Msg_id > 250)
						current_Msg_id = 1;
					Msg2HC.add(Msg);
					Msg.startTimer();
					Log.d("Service", "Msg2HC buffer=" + Msg2HC.size());
				} else if (MsgType == NetMessage.CMD_APP_CREATE_SCENE) {
					CreateScene appMsg = b
							.getParcelable("ContentProvider Message");
					Log.d("Service", "CP: New Msg, type = CreateModifyScene");
					// Create a new Msg2HC
					Message2HC Msg = new Message2HC(getApplicationContext(),
							current_Msg_id, appMsg, LumiHome.Timeout);
					current_Msg_id++;
					if (current_Msg_id > 250)
						current_Msg_id = 1;
					Msg2HC.add(Msg);
					Msg.startTimer();
					Log.d("Service", "Msg2HC buffer=" + Msg2HC.size());
				} else if (MsgType == NetMessage.CMD_APP_ACTIVATE_SCENE) {
					TurnOnScene appMsg = b
							.getParcelable("ContentProvider Message");
					Log.d("Service", "CP: New Msg, type = ActivateScene");
					// Create a new Msg2HC
					Message2HC Msg = new Message2HC(getApplicationContext(),
							current_Msg_id, appMsg, LumiHome.Timeout);
					current_Msg_id++;
					if (current_Msg_id > 250)
						current_Msg_id = 1;
					Msg2HC.add(Msg);
					Msg.startTimer();
					Log.d("Service", "Msg2HC buffer=" + Msg2HC.size());
				} else if (MsgType == NetMessage.CMD_APP_EDIT_SCENE) {
					EditScene appMsg = b
							.getParcelable("ContentProvider Message");
					Log.d("Service", "CP: New Msg, type = EditScene");
					// Create a new Msg2HC
					Message2HC Msg = new Message2HC(getApplicationContext(),
							current_Msg_id, appMsg, LumiHome.Timeout);
					current_Msg_id++;
					if (current_Msg_id > 250)
						current_Msg_id = 1;
					Msg2HC.add(Msg);
					Msg.startTimer();
					Log.d("Service", "Msg2HC buffer=" + Msg2HC.size());
				} else if (MsgType == NetMessage.CMD_APP_DEL_SCENE) {
					DelScene appMsg = b
							.getParcelable("ContentProvider Message");
					Log.d("Service", "CP: New Msg, type = DelScene");
					// Create a new Msg2HC
					Message2HC Msg = new Message2HC(getApplicationContext(),
							current_Msg_id, appMsg, LumiHome.Timeout);
					current_Msg_id++;
					if (current_Msg_id > 250)
						current_Msg_id = 1;
					Msg2HC.add(Msg);
					Msg.startTimer();
					Log.d("Service", "Msg2HC buffer=" + Msg2HC.size());
				} else if (MsgType == NetMessage.CMD_APP_CREATE_SCHEDULE) {
					// Hieu sua
					// DelScene appMsg =
					// b.getParcelable("ContentProvider Message");
					CreateSchedule appMsg = b
							.getParcelable("ContentProvider Message");
					// end
					Log.d("Service", "CP: New Msg, type = CreateSchedule");
					// Create a new Msg2HC
					Message2HC Msg = new Message2HC(getApplicationContext(),
							current_Msg_id, appMsg, LumiHome.Timeout);
					current_Msg_id++;
					if (current_Msg_id > 250)
						current_Msg_id = 1;
					Msg2HC.add(Msg);
					Msg.startTimer();
					Log.d("Service", "Msg2HC buffer=" + Msg2HC.size());
				} else if (MsgType == NetMessage.CMD_APP_EDIT_SCHEDULE) {
					EditSchedule appMsg = b
							.getParcelable("ContentProvider Message");
					Log.d("Service", "CP: New Msg, type = EditSchedule");
					// Create a new Msg2HC
					Message2HC Msg = new Message2HC(getApplicationContext(),
							current_Msg_id, appMsg, LumiHome.Timeout);
					current_Msg_id++;
					if (current_Msg_id > 250)
						current_Msg_id = 1;
					Msg2HC.add(Msg);
					Msg.startTimer();
					Log.d("Service", "Msg2HC buffer=" + Msg2HC.size());
				} else if (MsgType == NetMessage.CMD_APP_DEL_SCHEDULE) {
					DelSchedule appMsg = b
							.getParcelable("ContentProvider Message");
					Log.d("Service", "CP: New Msg, type = DelSchedule");
					// Create a new Msg2HC
					Message2HC Msg = new Message2HC(getApplicationContext(),
							current_Msg_id, appMsg, LumiHome.Timeout);
					current_Msg_id++;
					if (current_Msg_id > 250)
						current_Msg_id = 1;
					Msg2HC.add(Msg);
					Msg.startTimer();
					Log.d("Service", "Msg2HC buffer=" + Msg2HC.size());
				} else if (MsgType == NetMessage.CMD_APP_TOGGLE_SCHEDULE) {
					ToggleSchedule appMsg = b
							.getParcelable("ContentProvider Message");
					Message2HC Msg = new Message2HC(getApplicationContext(),
							current_Msg_id, appMsg, LumiHome.Timeout);
					current_Msg_id++;
					if (current_Msg_id > 250)
						current_Msg_id = 1;
					Msg2HC.add(Msg);
					Msg.startTimer();
					Log.e("ban tin", "CMD_TOOGLE");
				} else if (MsgType == NetMessage.CMD_APP_CHANGE_PASSWORD) {
					String pass = b.getString("PassWord");
					ChangePassWord changPwd = new ChangePassWord(0,
							LumiHome.Uid, LumiHome.Session_id, pass);
					Message2HC Msg = new Message2HC(getApplicationContext(),
							current_Msg_id, changPwd, LumiHome.Timeout);
					current_Msg_id++;
					if (current_Msg_id > 250)
						current_Msg_id = 1;
					Msg2HC.add(Msg);
					Msg.startTimer();
					Log.e("testSmart", "" + pass);
				}
				break;
			case RECEI2SER_NEW_MSG:
				// Take out the message
				Bundle b1 = new Bundle();
				b1 = msg.getData();
				byte[] content1 = b1.getByteArray(SmartHomeService.MESSAGE);
				Log.d("Service", "HC: New Msg" + Arrays.toString(content1));
				// check if this is a feedback message
				boolean isFeedbackMsg = false;
				boolean isHcBusying = false;
				if (Msg2HC.size() != 0) {
					int i = 0;
					while (i < Msg2HC.size()) {
						isFeedbackMsg = Msg2HC.get(i).isCorrectACK(content1);
						if (isFeedbackMsg)
							break;
						isHcBusying = Msg2HC.get(i).isBusyAck(content1);
						i++;
						if (isHcBusying)
							break;
					}
				}

				if (isFeedbackMsg == false && isHcBusying == false) {
					// if not feedback message
					switch (NetMessage.getCmdId(content1)) {
					case NetMessage.CMD_HC_UPDATE_DEVICE_STATUS:
						UpdateDeviceStatus update = new UpdateDeviceStatus(
								getApplicationContext());
						if (update.isCorrectFormat(content1, content1.length)) {
							update.parseMessage(content1, content1.length);
							update.doWhenReceived(getApplicationContext());
							Log.e("ban tin", "update deivice status");
						}
						break;
					case NetMessage.CMD_HC_UPDATE_SCENE_INFO:
						UpdateSceneInfo updateSceneInfo = new UpdateSceneInfo(
								LumiHome.Uid);
						if (updateSceneInfo.isCorrectFormat(content1,
								content1.length)) {
							updateSceneInfo.parseMessage(content1,
									content1.length);
							updateSceneInfo
									.doWhenReceived(getApplicationContext());
						}
						break;
					case NetMessage.CMD_HC_UPDATE_SCENE_ACTIVATED:
						UpdateSceneActivated updateSceneActivated = new UpdateSceneActivated(
								LumiHome.Uid);
						if (updateSceneActivated.isCorrectFormat(content1,
								content1.length)) {
							updateSceneActivated.parseMessage(content1,
									content1.length);
							updateSceneActivated
									.doWhenReceived(getApplicationContext());
						}
						break;
					case NetMessage.CMD_HC_UPDATE_SCENE_DELETED:
						UpdateSceneDeleted updateSceneDeleted = new UpdateSceneDeleted(
								LumiHome.Uid);
						if (updateSceneDeleted.isCorrectFormat(content1,
								content1.length)) {
							updateSceneDeleted.parseMessage(content1,
									content1.length);
							updateSceneDeleted
									.doWhenReceived(getApplicationContext());
						}
						break;
					case NetMessage.CMD_HC_UPDATE_SCHEDULE_INFO:
						UpdateScheduleInfo updateScheduleInfo = new UpdateScheduleInfo(
								LumiHome.Uid);
						if (updateScheduleInfo.isCorrectFormat(content1,
								content1.length)) {
							updateScheduleInfo.parseMessage(content1,
									content1.length);
							updateScheduleInfo
									.doWhenReceived(getApplicationContext());
						}
						break;
					case NetMessage.CMD_HC_UPDATE_SCHEDULE_STATE:
						UpdateScheduleState updateScheduleState = new UpdateScheduleState(
								LumiHome.Uid);
						if (updateScheduleState.isCorrectFormat(content1,
								content1.length)) {
							updateScheduleState.parseMessage(content1,
									content1.length);
							updateScheduleState
									.doWhenReceived(getApplicationContext());
						}
						break;
					case NetMessage.CMD_HC_UPDATE_SCHEDULE_DELETED:
						UpdateScheduleDeleted updateScheduleDeleted = new UpdateScheduleDeleted(
								LumiHome.Uid);
						if (updateScheduleDeleted.isCorrectFormat(content1,
								content1.length)) {
							updateScheduleDeleted.parseMessage(content1,
									content1.length);
							updateScheduleDeleted
									.doWhenReceived(getApplicationContext());
						}
						break;
					case NetMessage.CMD_HC_CAUTION_PR:
						CautionPrMessage cautionPrMsg = new CautionPrMessage();
						if (cautionPrMsg.isCorrectFormat(content1,
								content1.length)) {
							cautionPrMsg
									.parseMessage(content1, content1.length);
							cautionPrMsg
									.doWhenReceived(getApplicationContext());
						}
						break;
					}
				}
				break;
			case MSG_REGISTER_CLIENT:
				mClients.add(msg.replyTo);
				Log.d("Service", "New client: "
						+ msg.replyTo.getClass().getName());
				break;
			case MSG_UNREGISTER_CLIENT:
				mClients.remove(msg.replyTo);
				Log.d("Service", "Remove client: "
						+ msg.replyTo.getClass().getName());
				break;
			case RECON2SER_SUCESSFUL:
				LumiHome.SocketState = LumiHome.SOCKET_OPENED;
				Log.d("Service",
						"Reconnect Thread: Sucess, restart Receive Thread");
				transmitThread.Restart();
				receiveThread.Restart();
				// UI
				// DisplayHCReconnected();
				break;
			case RECON2SER_FAILED_CANNOT_CONNECT:
				LumiHome.SocketState = LumiHome.SOCKET_CLOSED;
				// bao len UI
				DisplayCannotConnectHC();
				break;
			case RECON2SER_FAILED_NONETWORK:
				LumiHome.SocketState = LumiHome.SOCKET_CLOSED;
				// bao len UI
				DisplayNoNetwork();
				break;
			case RECON2SER_FAILED_SESSION_DELETED:
				// now destroy all activities and back to login window
				Intent intent = new Intent(getApplicationContext(),
						MainActivity.class);
				intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
						| Intent.FLAG_ACTIVITY_NEW_TASK);
				intent.putExtra("finish", true);
				DisplayLoginAgain();
				startActivity(intent);
				break;
			default:
				super.handleMessage(msg);
			}
		}
	}

	private void DisplayNoNetwork() {
		DisplayToast(R.string.No_Wifi_3g, 1500);
		// Toast.makeText(this, R.string.No_Wifi_3g, Toast.LENGTH_LONG).show();
	}

	private void DisplayLoginAgain() {
		DisplayToast(R.string.txt_login_again, 1500);
	}

	public void DisplayToast(int textID, int miliseconds) {
		final Toast toast = Toast.makeText(getApplicationContext(), textID,
				Toast.LENGTH_SHORT);
		toast.show();
	}

	private void DisplayHCReconnected() {

		DisplayToast(R.string.HC_Reconnected, 1500);
	}

	private void DisplayCannotConnectHC() {
		DisplayToast(R.string.Cannot_connect_HC, 1500);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.d("Service", "onStartCommand");
		handleCommand(intent);
		// We want this service to continue running until it is explicitly
		// stopped, so return sticky.
		return startId;

	}

	private void handleCommand(Intent i) {

	}

	private void sendMessageToHC(Message msg) {
		transmitThread.getHandler().sendMessage(msg);
	}

	public class Message2HC {

		public static final int MSG_STATE_WAIT_TRANSMIT = 2;
		public static final int MSG_STATE_TRANSMITTED = 1;
		public static final int MSG_STATE_RETRY1 = 3;
		public static final int MSG_STATE_RETRY2 = 4;
		public static final int MSG_STATE_SUCESSFUL = 5;
		public static final int MSG_STATE_FAILED = 6;

		private AppMsg appMsg;
		public int Timeout = 0;
		// public int MaxRetry = 0;
		public int RetryTimes = 0;
		public Timer timer = null;
		protected int Msg_state = 0;
		private Context mContext;

		public Message2HC(Context context, int Msg_id, AppMsg appMsg,
				int Timeout) {
			this.appMsg = appMsg;

			// appMsg.setMsg_id(Msg_id);
			this.appMsg.setMsg_id(Msg_id);

			this.Timeout = LumiHome.Timeout;
			this.Msg_state = MSG_STATE_WAIT_TRANSMIT;
			this.mContext = context;
		}

		private void removeFromList(ArrayList<Message2HC> MsgList) {
			MsgList.remove(this);
		}

		public void startTimer() {
			this.Msg_state = MSG_STATE_WAIT_TRANSMIT;
			this.timer = new Timer();

			try {
				timer.scheduleAtFixedRate(new TimerTask() {
					@Override
					public void run() {
						if (LumiHome.SocketState == LumiHome.SOCKET_CLOSED) {
							Msg_state = MSG_STATE_FAILED;
							appMsg.doIfSendFail(mContext);
							Log.d("Service",
									"Socket is closed, try reconnect now, Send msg failed:"
											+ Arrays.toString(appMsg
													.generateByteArray()));
							removeFromList(Msg2HC);
							reconnectHC();
							this.cancel();
							return;
						} else if (LumiHome.SocketState == LumiHome.SOCKET_RECONNECTING) {
							Msg_state = MSG_STATE_FAILED;
							appMsg.doIfSendFail(mContext);
							Log.d("Service",
									"Socket is closed, Send msg failed:"
											+ Arrays.toString(appMsg
													.generateByteArray()));
							removeFromList(Msg2HC);
							this.cancel();
							return;
						}
						if (Msg_state == MSG_STATE_WAIT_TRANSMIT) {
							final Message msg = Message.obtain();
							msg.what = SmartHomeService.SER2TRAN_NEW_MSG;
							Bundle b = new Bundle();
							b.putByteArray(SmartHomeService.MESSAGE,
									appMsg.generateByteArray());
							msg.setData(b);
							// send
							Log.d("Service",
									"Msg to Transmit Thread, time=1:"
											+ Arrays.toString(appMsg
													.generateByteArray()));
							sendMessageToHC(msg);
							Msg_state = MSG_STATE_TRANSMITTED;
						} else if (Msg_state == MSG_STATE_TRANSMITTED) {
							final Message msg = Message.obtain();
							msg.what = SmartHomeService.SER2TRAN_NEW_MSG;
							Bundle b = new Bundle();
							b.putByteArray(SmartHomeService.MESSAGE,
									appMsg.generateByteArray());
							msg.setData(b);
							// send
							Log.d("Service",
									"Msg to Transmit Thread, time=2:"
											+ Arrays.toString(appMsg
													.generateByteArray()));
							sendMessageToHC(msg);
							Msg_state = MSG_STATE_RETRY1;
						} else if (Msg_state == MSG_STATE_RETRY1) {
							final Message msg = Message.obtain();
							msg.what = SmartHomeService.SER2TRAN_NEW_MSG;
							Bundle b = new Bundle();
							b.putByteArray(SmartHomeService.MESSAGE,
									appMsg.generateByteArray());
							msg.setData(b);
							// send
							Log.d("Service",
									"Msg to Transmit Thread, time=3:"
											+ Arrays.toString(appMsg
													.generateByteArray()));
							sendMessageToHC(msg);
							Msg_state = MSG_STATE_RETRY2;
						} else if (Msg_state == MSG_STATE_RETRY2) {
							Msg_state = MSG_STATE_FAILED;
							appMsg.doIfSendFail(mContext);
							Log.d("Service",
									"Send msg failed:"
											+ Arrays.toString(appMsg
													.generateByteArray()));
							removeFromList(Msg2HC);
							reconnectHC();
							this.cancel();
						}
					}
				}, 0, this.Timeout);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		public boolean isCorrectACK(byte[] Msg) {
			boolean result = false;
			if (Msg == null)
				result = false;
			else if (appMsg.isCorrectReply(Msg, Msg.length)) {
				result = true;
				this.Msg_state = MSG_STATE_SUCESSFUL;
				this.timer.cancel();
				Log.d("Service",
						"Send msg successful:"
								+ Arrays.toString(appMsg.generateByteArray()));
				appMsg.doIfSendSuccessful(mContext);
				// self destroy
				removeFromList(Msg2HC);
				Log.d("Service", "Msg2HC buffer=" + Msg2HC.size());
			}
			return result;
		}

		public boolean isBusyAck(byte[] Msg) {
			boolean result = false;

			if (Msg == null)
				result = false;
			else if (appMsg.isCorrectBusy(Msg, Msg.length)) {
				result = true;
				this.Msg_state = MSG_STATE_WAIT_TRANSMIT;
				Log.e("ban tin", "HC is busy");
			}
			return result;
		}
	}

	private void reconnectHC() {
		// Inform user
		// Message msg = toastHandler.obtainMessage();
		// msg.what = MSG_DISPLAY_TOAST;
		// Bundle b= new Bundle();
		// b.putInt(ToastTextKey, R.string.HC_Connection_broken);
		// msg.setData(b);
		// toastHandler.sendMessage(msg);
		// close socket

		try {
			ReceiveDataThread.End();
			TransmitThread.End();
			LumiHome.socket.close();
			LumiHome.is.close();
			LumiHome.os.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			Log.d("Service", "Can not close socket");
			return;
		}
		LumiHome.SocketState = LumiHome.SOCKET_RECONNECTING;
		receiveThread.Pause();
		// reopen socket
		ReconnectThread reconnect = new ReconnectThread(this.mHandler,
				this.getApplicationContext());
		reconnect.start();
	}
}
